﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;

namespace IronCow.Posh.Commands
{
    [Cmdlet(VerbsCommon.Get, "RtmTask", DefaultParameterSetName = "Filter")]
    [System.ComponentModel.Description("Gets RTM tasks.")]
    public class GetRtmTaskCommand : RtmCmdlet
    {
        #region Cmdlet Parameters
        [Parameter(
            Mandatory = false,
            Position = 1,
            ParameterSetName = "Filter",
            ValueFromPipeline = true,
            HelpMessage = "The search query to use to get the tasks.")]
        [Parameter(Mandatory = false, ParameterSetName = "ListId")]
        [Parameter(Mandatory = false, ParameterSetName = "ListName")]
        public string Filter { get; set; }

        [Parameter(
            Mandatory = true,
            ParameterSetName = "ListId",
            HelpMessage = "The ID of the task list from which to get the tasks.")]
        [Parameter(Mandatory = true, ParameterSetName = "SeriesId")]
        [Parameter(Mandatory = true, ParameterSetName = "TaskId")]
        public string ListId { get; set; }

        [Parameter(
            Mandatory = true,
            ParameterSetName = "SeriesId",
            HelpMessage = "The ID of the task series from which to get the tasks.")]
        [Parameter(Mandatory = true, ParameterSetName = "TaskId")]
        public string SeriesId { get; set; }

        [Parameter(
            Mandatory = true,
            ParameterSetName = "TaskId",
            HelpMessage = "The ID of the task to get.")]
        public string TaskId { get; set; }

        [Parameter(
            Mandatory = true,
            ParameterSetName = "ListName",
            HelpMessage = "The name of the task list from which to get the tasks. Wildcards are supported.")]
        [ValidateNotNullOrEmpty]
        public string ListName { get; set; }

        [Parameter(
            Mandatory = false,
            ParameterSetName = "Filter",
            HelpMessage = "Controls whether only incomplete tasks are returned. This parameter is ignored if you use the \"status:\" operator in the filter parameter.")]
        [Parameter(Mandatory = false, ParameterSetName = "ListName")]
        [Parameter(Mandatory = false, ParameterSetName = "ListId")]
        [Parameter(Mandatory = false, ParameterSetName = "SeriesId")]
        [System.ComponentModel.DefaultValue(true)]
        public bool IncompleteOnly { get; set; } 
        #endregion

        #region Construction
        public GetRtmTaskCommand()
        {
            IncompleteOnly = true;
        } 
        #endregion

        #region Record Processing
        protected override void ProcessRecord()
        {
            switch (ParameterSetName)
            {
                case "Filter":
                    ProcessRecordByFilter();
                    break;
                case "ListName":
                    ProcessRecordByListName();
                    break;
                case "ListId":
                    ProcessRecordByListId();
                    break;
                case "SeriesId":
                    ProcessRecordBySeriesId();
                    break;
                case "TaskId":
                    ProcessRecordByTaskId();
                    break;
            }
        }

        private void ProcessRecordByTaskId()
        {
            TaskList taskList = Rtm.TaskLists.GetById(ListId, true);
            Task task = taskList.Tasks.GetById(SeriesId, TaskId);
            WriteObject(task);
        }

        private void ProcessRecordBySeriesId()
        {
            TaskList taskList = Rtm.TaskLists.GetById(ListId, true);
            foreach (Task task in taskList.Tasks)
            {
                if (task.SeriesId == SeriesId &&
                    (!IncompleteOnly || task.IsIncomplete))
                    WriteObject(task);
            }
        }

        private void ProcessRecordByListId()
        {
            TaskList taskList = Rtm.TaskLists.GetById(ListId, true);
            ProcessRecordByFilter(string.Format("list:\"{0}\"", taskList.Name));
        }

        private void ProcessRecordByListName()
        {
            // Get the task lists matching the given name/pattern.
            var taskLists = new List<TaskList>();
            WildcardPattern pattern = new WildcardPattern(ListName, WildcardOptions.IgnoreCase);
            foreach (TaskList taskList in Rtm.TaskLists)
            {
                if (pattern.IsMatch(taskList.Name))
                    taskLists.Add(taskList);
            }
            if (taskLists.Count == 0)
                throw new Exception(string.Format("No task list found matching: '{0}'", ListName));

            // Build the search query.
            StringBuilder query = new StringBuilder();
            for (int i = 0; i < taskLists.Count; i++)
            {
                if (i > 0) query.Append(" AND ");
                query.AppendFormat("list:\"{0}\"", taskLists[i].Name);
            }
            ProcessRecordByFilter(query.ToString());
        }

        private void ProcessRecordByFilter()
        {
            ProcessRecordByFilter(Filter);
        }

        private void ProcessRecordByFilter(string filter)
        {
            if (IncompleteOnly && !filter.Contains("status:"))
            {
                filter = "status:incomplete AND (" + filter + ")";
            }
            WriteObject(Rtm.GetTasks(null, filter), true);
        }
        #endregion
    }
}
